Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
inherits-ex
Advanced tools
Browser-friendly enhanced inheritance fully compatible with standard node.js inherits with dynamic inheritance or creation.
This package modifies and enhances the standard inherits
from node.js
util
module in node environment. It also has a shim for old
browsers with no Object.create
support.
Differs from the standard implementation is:
isInheritedFrom(ctor, superCtor|superCtorName)
Check the ctor whether inherited from superCtormixin(ctor, superCtor|superCtor[])
Mixin the methods and properties of the SuperCtor:
isMixinedFrom(ctor, superCtor|superCtorName)
Whether mixined from superCtorcreateCtor(name, args, body)
Create Ctor(Class) dynamicallycreateObject(ctor, args...)
Create Object instance dynamicallycreateFunction(name, [args,] body[, scope[, values]])
Create Function dynamicallyThe standard inherits
implementation is in inherits-ex/lib/inheritsDirectly
,
of cause it's the coffee-script supports and browser-friendly.
Full API see the folder: docs
function inherits(ctor, superCtor|superCtor[], staticInherit = true): boolean
A powerful tool for implementing class inheritance that supports dynamic inheritance and multiple inheritance.
Features:
staticInherit
(boolean): whether static inheritance,defaults to true.The function is compatible with both ES5 and ES6, as well as older browsers that do not support these versions of JavaScript. The function also supports CoffeeScript-generated classes.
import inherits from 'inherits-ex/lib/inherits'
Note:
inherits
function, two properties, super_
and __super__
, are added to the constructor function (ctor
).
super_
property refers to the parent constructor.__super__
property refers to the parent's prototype object, which can be used for the super
keyword in CoffeeScript.Class
property is added to the prototype object of the constructor function (ctor
).
ctor
).ctor
may not be the current class, but the Class
property is always set to the current class for instance.The default constructor chain in ES6 Class may fail if the constructor is empty, because the constructor cannot be directly called if the Reflect.construct(target, args, newTarget)
native method is not supported. In such a case, you may need to manually define a constructor or use a polyfill to support the Reflect.construct()
method.
import { defineProperty, getOwnPropValue, getPrototypeOf, inherits } from 'inherits-ex'
// Or use function class instead of ES6 class:
// function Root() {this.initialize.apply(this, arguments)}
// Root.prototype.initialize = function initialize() {console.log('Root.init')}
class Root {
constructor() {
this.initialize.apply(this, arguments)
}
initialize() {
console.log('Root.init')
}
}
class A {
/*
If you encounter issues with the inherits function and the default constructor chain in ES6 class, you may need to add a constructor function to the derived class in order to call the parent constructor. Alternatively, you can use the traditional function syntax to define your classes and implement inheritance, rather than the ES6 class syntax. For example, you can define a root function and a derived function using the traditional syntax, and then use the inherits function to implement inheritance between them. This way, you can avoid the issue of needing to define a constructor in the derived class.
*/
constructor() {
// this `Class` prop is only created by the `inherits` function or `newPrototype` function.
// make sure the current `constructor.prototype` whether has the property 'Class'
if (!getOwnPropValue(getPrototypeOf(this), 'Class')) {
const proto = getPrototypeOf(this)
const cls = proto.constructor
defineProperty(this, 'Class', cls)
if (!cls.__super__) defineProperty(cls, '__super__', getPrototypeOf(proto))
}
const Parent = getParentClass(this.Class)
// create the instance by calling the parent constructor
return Reflect.construct(Parent, arguments, this.Class)
// or call initialize method directly
// this.initialize.apply(this, arguments)
}
initialize() {
const ParentPrototype = this.Class.__super__
ParentPrototype.init.apply(this, arguments)
console.log('A.init')
}
}
inherits(A, Root)
const obj = new A() // Bug: The initialize method can not be executed if no process in constructor.
import assert from 'assert'
import inherits from 'inherits-ex/lib/inherits'
import isInheritedFrom from 'inherits-ex/lib/isInheritedFrom'
import getParentClass from 'inherits-ex/lib/getParentClass'
import getSuper from 'inherits-ex/lib/getSuper'
const log = console.log.bind(console)
class Root{
m() {log('root')}
}
class A{
m(){
log('A')
getSuper(this).m.call(this)
// super.m()
}
}
inherits(A, Root)
class B {
m() {
log('B')
getSuper(this).m.call(this)
// super.m()
}
}
inherits(B, Root)
class MyClass {
}
// MyClass -> A -> Root
inherits(MyClass, B)
// MyClass -> A -> B -> Root
inherits(MyClass, A)
// duplication inheritances prohibited.
assert.notOk(inherits(A, Root))
assert.ok(isInheritedFrom(MyClass, A))
assert.ok(isInheritedFrom(MyClass, Root))
assert.ok(isInheritedFrom(MyClass, B))
and the following codes do same thing:
class Root {
static static = 1
m() {log('root')}
}
class A {
m() {
log('A')
super.m()
}
}
class B {
m() {
log('B')
super.m()
}
}
class MyClass {
}
// Create inheritances chain: MyClass -> A -> B -> Root
inherits(MyClass, [A, B, Root])
assert.ok(isInheritedFrom(MyClass, A))
assert.ok(isInheritedFrom(MyClass, Root))
assert.ok(isInheritedFrom(MyClass, B))
assert.equal(MyClass.static, 1)
Enables dynamic prototypal inheritance between classes, allowing for flexible and reusable code.
inheritsDirectly(ctor:Function, superCtor:Function, staticInherit = true)
staticInherit
(boolean): whether static inheritance,defaults to true. import inheritsDirectly from 'inherits-ex/lib/inheritsDirectly'
The inheritsDirectly
function is compatible with both ES5 and ES6, as well as older browsers that do not support these versions of JavaScript.
The function also supports CoffeeScript-generated classes
Note: If a parent class already exists on the class, it will be replaced by the new parent class.
Determines if a constructor(class) is inherited from a given super constructor(class).
isInheritedFrom(ctor, superCtor|superCtorName, raiseError=false)
import isInheritedFrom from 'inherits-ex/lib/isInheritedFrom'
return the superCtor's son if ctor is inherited from superCtor. else return false.
it will use the ctor.name to check whether inherited from superCtorName.
mixin(ctor:Function, superCtor:Function|Function[], options:{ filter: number|function})
Mixin the methods and properties of the SuperCtor: Clone(Copy) all superCtor
's properties(methods) to ctor.
Mixes the methods and properties from one or more classes to the target class.
By default, all properties and methods from the superCtors
will be cloned into the internal mixinCtor_
constructor of the target class(ctor
). This can be customized by providing the options.filter
parameter.
If the target class does not already have a mixinCtor_
constructor it'll create the new constructor
mixinCtor_
which is then inherited by the ctor
(target class). The mixinCtor_
is also set as a property of the
ctor
.
0
: copy all properties(methods)1
: raise error if found a method using super
2
: skip these methods which using super
string[]
: only name in the array of string will be copied.function(name, value){return value}
the callback function of filter.
name
: the property namevalue
: the property value. import mixin from 'inherits-ex/lib/mixin'
mixin all superCtors to ctor.
super()
will jump to the old class(not stay on the class).MixinCtor_
)
ctor -> MixinCtor_ -> original parents
const mCallOrder = []
class Root {}
class C extends Root {
m() {
mCallOrder.push('C')
super()
}
}
class A {
m() {
mCallOrder.push('A')
}
}
class A1 extends A {
m() {
mCallOrder.push('A1')
super()
}
}
class B {}
inherits(B, Root)
class B1 extends B {
m() {
mCallOrder.push('B1')
super()
}
}
mixin(B1, [A1, C]).should.be.equal(true, 'mixin')
const o = new B1()
o.m("a", 12) // call chain: B1::m -> C::m
A::m.should.have.been.calledOnce
A::m.should.have.been.calledWith("a", 12)
mCallOrder.should.be.deep.equal(['B1', 'C'])
The inheritance chain: B1 -> MixinCtor_ -> B -> Root
All mixins will be added to MixinCtor_
.
isMixinedFrom(ctor: Function, superCtor: Function|string)
Check if a constructor(ctor
) is mixed from a specific constructor(superCtor
).
import isMixinedFrom from 'inherits-ex/lib/isMixinedFrom'
createCtor(name: string, args: Array|string, body: string|null|undefined): Function
Create a constructor(class) dynamically.
Creates a constructor function dynamically with the given name, arguments, and body.
If the arguments are a string, it is assumed to be the body and the arguments are set to an empty array.
If the body is null or undefined, a default body is created that calls the parent constructor.
name
(string): the class name
args
(any[]): the optional constructor's args.
body
(string): the optional constructor function body.
import createClass from 'inherits-ex/lib/createCtor'
const MyClass = createClass('MyClass', ['a', 'b'], 'this.sum = a + b');
var my = new MyClass(1, 2);
console.log(my.sum);
createObject(ctor: Function, ...args)
The helper function to create the object dynamically and arguments provided individually.
import createObject from 'inherits-ex/lib/createObject'
class MyClass {
constructor(a,b) {
this.sum = a + b;
}
}
var o = createObject(MyClass, 1, 2)
console.log(o.sum)
NOTE: It will call the parent constructor if the class is the Empty constructor.
import inherits from 'inherits-ex/lib/inherits'
import createObject from 'inherits-ex/lib/createObject'
class Root {
constructor() {
this.init = 'root'
}
}
class MyClass {
}
inherits(MyClass, Root)
var obj = createObject(MyClass)
assert.equal(obj.init, 'root')
Usage:
class RefObject {
constructor() {this.initialize.apply(this, arguments)}
}
class MyObject {
initialize(a, b) {
this.a = a
this.b = b
}
}
inherits(MyObject, RefObject)
obj = createObject(MyObject, "a", "b")
// obj = new MyObject("a", "b") // it will have no property a and b.
assert.equal(obj.a, "a")
assert.equal(obj.b, "b")
createObjectWith(ctor, args: Array)
The helper function to create the object dynamically. provides the arguments as an array (or an array-like object).
import createObjectWith from 'inherits-ex/lib/createObjectWith'
const obj = createObjectWith(MyObject, ['a', 'b'])
NOTE: It will call the parent constructor if the class is the Empty constructor.
createFunction(name: string, [args,] body[, scope[, values]])
name
(String): the function nameargs
(Array): the function argument list. it's optional.body
(String): the function body.values
if it's an object.value
is required if it's an array. It's the key's name listvalue
(Array): the optional function scope's value list. only for the scope
is the Array.The helper function to create the function dynamically.
import createFunction from 'inherits-ex/lib/createFunction'
FAQs
Enhanced inheritance for dynamic inheritance and mixin.
We found that inherits-ex demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.